home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / smoke / smoke.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  9KB  |  369 lines

  1. /*
  2.  * Copyright (c) 1993, 1994, Silicon Graphics, Inc.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software
  5.  * and its documentation for any purpose is hereby granted without
  6.  * fee, provided that (i) the above copyright notices and this
  7.  * permission notice appear in all copies of the software and related
  8.  * documentation, and (ii) the name of Silicon Graphics may not be
  9.  * used in any advertising or publicity relating to the software
  10.  * without the specific, prior written permission of Silicon Graphics.
  11.  * 
  12.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  13.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  14.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  15.  * 
  16.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL,
  17.  * INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
  18.  * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY
  20.  * THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE
  21.  * OR PERFORMANCE OF THIS SOFTWARE.
  22.  * 
  23.  */
  24.  
  25.  
  26. #include "uSmoke.h"
  27. #include "uLinMath.h"
  28. #include "smoke_ext.h" /* extern'd variables used in this module */
  29.  
  30.  
  31. /*************************************************************/
  32.  
  33. /* [ 13A-1 ] */
  34. void initPuff(uPuff *puff, uSmoke *smoke)
  35. {
  36.     float     *rv, r,s;
  37.     float    offset[3];
  38.     float    mat[4][4];
  39.     long    i;
  40.  
  41.     if(InitRand == 0)
  42.     {
  43.     for(i=0; i<MAX_RAND; i++)
  44.     {
  45.         RandVec3[i][0] = (float)(random() & 0xffff) / 32767.0f - 1.0f;
  46.         RandVec3[i][1] = (float)(random() & 0xffff) / 32767.0f - 1.0f;
  47.         RandVec3[i][2] = (float)(random() & 0xffff) / 32767.0f - 1.0f;
  48.  
  49.         uNormalizeVec3(RandVec3[i]);
  50.     }
  51.  
  52.     InitRand = 1;
  53.     }
  54.  
  55.     puff->radius = smoke->radius;
  56.     uCopyVec3(puff->origin, smoke->origin);
  57.     puff->transp = 0.0f;
  58.     puff->startTime = smoke->lastPuffTime;
  59.  
  60.     /* Add random velocity modifier */
  61.     if(smoke->type != USMOKE_MISSLE)
  62.     {
  63.         rv = RAND_VEC3;
  64.         uAddScaledVec3(puff->direction, smoke->direction, .15f, rv);
  65.     }
  66.     else
  67.         uCopyVec3(puff->direction, smoke->direction);
  68.  
  69.     s = smoke->expansion * smoke->radius * .05f;
  70.     uScaleVec3(offset, s, puff->direction); /*puff->direction was rv, ?bug?*/
  71.     uAddVec3(puff->origin, puff->origin, offset);
  72.  
  73.     r = ((random() & 0xff) / 255.0f - .5f) * 4.0f * smoke->turbulence;
  74.  
  75.     uMakeTransMat(puff->rotMat, -0.5f, -0.5f, 0.0f);
  76.     uMakeRotMat(mat, r, 0.0f, 0.0f, 1.0f);
  77.     uPostMultMat(puff->rotMat, mat);
  78.     uMakeTransMat(mat, 0.5f, 0.5f, 0.0f);
  79.     uPostMultMat(puff->rotMat, mat);
  80.  
  81.     r = 1.0f + ((random() & 0xffff) / 65535.0f + -.5f) * .1f;
  82.  
  83.     puff->speed = r * smoke->speed;
  84. }
  85.  
  86. /* [ 13A ] */
  87. void drawSmoke(uSmoke *smoke, uVec3 eye)
  88. {
  89.     double     now = uGetTime();
  90.     double    deltaTime, age = 1.0f;
  91.     float    speed, *tmp;
  92.     float    puffInterval, puffDiss;
  93.     uVec3    dist;
  94.     long    i, n, startPuff;
  95.  
  96.     /* Compute time elapsed from previous uDrawSmoke */
  97.     if(smoke->prevTime < 0.0f)
  98.     deltaTime = 0.0f;
  99.     else
  100.         deltaTime = now - smoke->prevTime;
  101.  
  102.     smoke->prevTime = now;
  103.  
  104.     if(smoke->startTime < 0.0f)
  105.     smoke->startTime = now;
  106.  
  107.     if(smoke->duration > 0.0f)
  108.     {
  109.         age = 1.0 - (now - smoke->startTime) / smoke->duration;
  110.  
  111.         if(age <= 0.0)
  112.         {
  113.         smoke->mode = USMOKE_STOP;
  114.         smoke->startTime = -1.;
  115.         smoke->lastPuffTime = -1.;
  116.         return;
  117.         }
  118.  
  119.     age += .01f;
  120.     }
  121.  
  122.     if (smoke->type != USMOKE_EXPLOSION)
  123.     {
  124.     puffInterval = smoke->puffInterval / age;
  125.     puffDiss = smoke->dissipation/smoke->density * age; /*needed density*/
  126.     }
  127.     else
  128.     {
  129.     puffInterval = smoke->puffInterval;
  130.     puffDiss = smoke->dissipation/smoke->density;
  131.     }
  132.    
  133.     /* Initialize new puff of smoke if necessary */
  134.     if(now - smoke->lastPuffTime >= puffInterval)
  135.     {
  136.     uPuff    *puff;
  137.  
  138.     smoke->lastPuffTime = now;
  139.     puff = smoke->puffs[(smoke->startPuff + smoke->numPuffs) % MAX_PUFFS];
  140.                         
  141.     initPuff(puff, smoke); /* 13A-1*/
  142.  
  143.     smoke->numPuffs++;
  144.     }
  145.  
  146.     if(smoke->tex) {
  147.         uApplyTex(smoke->tex);
  148.     }
  149.  
  150.     n = smoke->numPuffs;
  151.     startPuff = smoke->startPuff;
  152.  
  153.     for(i=n-1; i>=0; i--)
  154.     {
  155.     uPuff *puff = smoke->puffs[(i+startPuff) % MAX_PUFFS];
  156.  
  157.     /* 
  158.      * Dissipate puff based on dissipation rate 
  159.     */
  160.     puff->t = (now - puff->startTime) / puffDiss;
  161.  
  162.     /* Get rid of puff if completely transparent */
  163.     if(puff->t >= 1.0f)
  164.     {        
  165.         smoke->startPuff = (smoke->startPuff + 1) % MAX_PUFFS;
  166.         smoke->numPuffs--;
  167.         continue;
  168.     }
  169.  
  170.     /* 
  171.      * Transparency is cubed so it quickly dissipates as dissipation
  172.      * time is neared.
  173.     */
  174.     puff->transp = puff->t * puff->t * puff->t * puff->t;
  175.  
  176.     if(smoke->type == USMOKE_EXPLOSION)
  177.     {
  178.         /* Radius is linear interpolation between 0 and expansion */
  179.         puff->radius = (now - puff->startTime) / puffDiss * 
  180.                 smoke->expansion * smoke->radius;
  181.     }
  182.     else
  183.     {
  184.         /* Radius is linear interpolation between radius and expansion */
  185.         puff->radius = (1.0f - puff->transp) * smoke->radius + 
  186.             puff->transp * smoke->expansion * smoke->radius;
  187.     }
  188.  
  189.         speed = puff->speed * deltaTime;
  190.        uScaleVec3(dist, speed, puff->direction);
  191.  
  192.     /* Translate puff based on velocity vector */
  193.     {
  194.          tmp = puff->origin;
  195.         uAddVec3(tmp, tmp, dist);
  196.     }
  197.  
  198.     /* Fade in brand new puff */
  199.     if(i == smoke->numPuffs - 1 
  200.        && smoke->type != USMOKE_EXPLOSION && smoke->type != USMOKE_FIRE)
  201.     {
  202.         puff->transp = 1.0f - (now - puff->startTime) / puffInterval;
  203.     }
  204.  
  205.     drawPuff(puff, smoke, eye);
  206.     }
  207. }
  208.  
  209. #define SQRT3_2    .86602540378443864676f
  210.  
  211. void cross(uVec3 AN, uVec3 BN, uVec3 CN, float *nx, float *ny, float *nz);
  212.  
  213. /* [ 13B ] */
  214. void drawPuff(uPuff *puff, uSmoke *smoke, uVec3 eye)
  215. {
  216.     uVec4        opaque;
  217.     long    i;
  218.     float    r = puff->radius, *org = puff->origin;
  219.  
  220.     uVec3        norm,norm_d; 
  221.     static int pc=0;
  222.     float *t2;
  223.     #define Zv 0.0
  224.     static float t2a[]={0,0,1,0,1,1,0,1};
  225.     static float t2b[]={1,0,Zv,1,1,Zv,0,1,Zv,0,0,Zv};
  226.     static float t2c[]={1,1,0,1,0,0,1,0};
  227.     static float t2d[]={0,1,0,0,1,0,1,1};
  228.  
  229.     static uVec3 quad[] = {
  230.     {-1.0f, 0.0f, -1.0f},
  231.     {1.0f, 0.0f, -1.0f},
  232.     {1.0f, 0.0f, 1.0f},
  233.     {-1.0f, 0.0f, 1.0f}
  234.     }; 
  235.     uVec3              dquad[6], toEye;
  236.  
  237.     uMatrix        mat;
  238.     static uVec3    vec = {0.0f, -1.0f, 0.0f};
  239.  
  240.     /* Fade fire to black smoke */
  241.     if (smoke->type == USMOKE_FIRE)
  242.     {
  243.       uAddScaledVec3(opaque, smoke->bgnColor, puff->transp, smoke->deltaColor);
  244.       opaque[3] = 1.0f;
  245.     }
  246.     else
  247.     {
  248.       uAddScaledVec3(opaque, smoke->bgnColor, puff->t, smoke->deltaColor);
  249.  
  250.       opaque[3] = 1.0f - puff->transp;
  251.     }
  252.  
  253.     /* 
  254.      * Compute matrix which rotates puff to face the eyepoint 
  255.     */
  256.     uSubVec3(toEye, eye, puff->origin);
  257.  
  258.     uMakeRotOntoMat(mat, vec, toEye);
  259.  
  260.     for(i=0; i<4; i++)
  261.     {
  262.     uVec3        svert;
  263.  
  264.     /* Scale quad to current radius */
  265.     uScaleVec3(svert, puff->radius, quad[i]);
  266.  
  267.     /* Offset puff based on radius */
  268.     svert[1] -= smoke->radius;
  269.  
  270.     /* Rotate puff to follow viewer */
  271.     uXformPt3(dquad[i], svert, mat);
  272.  
  273.     /* Translate puff to origin */
  274.         uAddVec3(dquad[i], dquad[i], puff->origin);
  275.  
  276.     }
  277.  
  278. #if 0
  279.     switch(pc++) {
  280.     case 0:
  281.        t2 = t2b;
  282.        break;
  283.     case 1:
  284.        t2 = t2c;
  285.        break;
  286.     case 2:
  287.        t2 = t2d;
  288.        break;
  289.     case 3:
  290.        t2 = t2a;
  291.        pc = 0;
  292.        break;
  293.     }
  294. #else
  295.     t2 = t2b;
  296. #endif
  297. #if NOTEXTURE
  298.     #define T2F(t)
  299. #else  
  300.     #define T2F(t)  t2f((t))
  301. #endif
  302.  
  303.     lmcolor(LMC_DIFFUSE);
  304.     c4f(opaque);
  305.     bgnpolygon();
  306.         cross(dquad[0],dquad[1],dquad[2],&norm[0],&norm[1],&norm[2]);
  307.     norm_d[0]=(dquad[0][0]-norm[0]);
  308.     norm_d[1]=(dquad[0][1]-norm[1]);
  309.     norm_d[2]=(dquad[0][2]-norm[2]);
  310.         n3f(norm);
  311.     T2F(t2);
  312.         v3f(dquad[0]);
  313.     T2F(t2+3);
  314.         v3f(dquad[1]);
  315.     T2F(t2+6);
  316.         v3f(dquad[2]);
  317.     T2F(t2+9);
  318.         v3f(dquad[3]);
  319.     endpolygon();
  320.  
  321. #if NOTEXTURE
  322.     bgnline();
  323.        v3f(dquad[0]);
  324.        v3f(norm_d);
  325.     endline();
  326. #endif
  327. }
  328.  
  329. #define X1 AN[0]
  330. #define Y1 AN[1]
  331. #define Z1 AN[2]
  332.  
  333. #define X2 BN[0]
  334. #define Y2 BN[1]
  335. #define Z2 BN[2]
  336.  
  337. #define X3 CN[0]
  338. #define Y3 CN[1]
  339. #define Z3 CN[2]
  340.  
  341. void cross(uVec3 AN, uVec3 BN, uVec3 CN, float *nx, float *ny, float *nz)
  342. {
  343.     float vx1,vy1,vz1, vx2,vy2,vz2, x,y,z, dis;
  344.     /* find the two vectors */
  345.  
  346.     vx1 = X1-X2;
  347.     vy1 = Y1-Y2;
  348.     vz1 = Z1-Z2;
  349.  
  350.     vx2 = X3-X2;
  351.     vy2 = Y3-Y2;
  352.     vz2 = Z3-Z2;
  353.  
  354.     /* get their cross product */
  355.  
  356.     x = vy1*vz2 - vz1*vy2;
  357.     y = vz1*vx2 - vx1*vz2;
  358.     z = vx1*vy2 - vy1*vx2;
  359.  
  360.       dis = sqrtf(x*x + y*y + z*z);
  361.       if(dis == 0.0) dis=0.000001;
  362.  
  363.       *nx = -x/dis;
  364.       *ny = -y/dis;
  365.       *nz = -z/dis;
  366.       
  367. } /* cross_product */
  368.  
  369.